﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ChemicalEquilibrium
{
    public class ReactIngest
    {
        Queue<Reactant> As, A_s, Bs, B_s, Cs, C_s;
        int Volume;
        int IngestVelocity, ReleaseVelocity;

        /// <summary>
        /// 反应物摄入与释放
        /// </summary>
        /// <param name="As">满容器物</param>
        /// <param name="A_s">空容器物</param>
        /// <param name="Bs">摄入物</param>
        /// <param name="B_s">释放物</param>
        /// <param name="Cs">摄入催化酶</param>
        /// <param name="C_s">释放催化酶</param>
        /// <param name="count">容量</param>
        public ReactIngest(Queue<Reactant> As, Queue<Reactant> A_s, Queue<Reactant> Bs, Queue<Reactant> B_s, Queue<Reactant> Cs, Queue<Reactant> C_s, int volume)
        {
            this.As = As;
            this.A_s = A_s;
            this.Bs = Bs;
            this.B_s = B_s;
            this.Cs = Cs;
            this.C_s = C_s;

            this.Volume = volume;
        }

        //摄入
        public void Ingest()
        {
            if (As == null || Bs == null || Bs == null || B_s == null) throw new Exception("Ingest Error : Reactant is null!");

            if (this.Bs.Count > this.Volume)
            {
                if (this.Cs != null)
                {
                    if (this.A_s.Count * this.Cs.Count == 0)
                        this.IngestVelocity = 0;
                    else if (A_s.Count * Cs.Count / (A_s.Count + Cs.Count) < 10)
                        this.IngestVelocity = 1;
                    else
                        this.IngestVelocity = A_s.Count * Cs.Count / (A_s.Count + Cs.Count) / 10;
                }
                else
                    this.IngestVelocity = (A_s.Count + 9) / 10;

                for (int i = 0; i < this.IngestVelocity; i++)
                {
                    if (this.Bs.Count < this.Volume) break;

                    Reactant A_ = this.A_s.Dequeue();

                    for (int j = 0; j < this.Volume; j++)
                    {
                        A_.Combine(this.Bs.Dequeue());
                    }

                    this.As.Enqueue(A_);
                }
            }
        }

        //释放
        public void Release()
        {
            if (As == null || Bs == null || Bs == null || B_s == null) throw new Exception("Release Error : Reactant is null!");

            if (this.C_s != null)
            {
                if (this.As.Count * this.C_s.Count == 0)
                    this.ReleaseVelocity = 0;
                else if (As.Count * C_s.Count / (As.Count + C_s.Count) < 10)
                    this.ReleaseVelocity = 1;
                else
                    this.ReleaseVelocity = As.Count * C_s.Count / (As.Count + C_s.Count) / 10;
            }
            else
                this.ReleaseVelocity = (As.Count + 9) / 10;

            for (int i = 0; i < this.ReleaseVelocity; i++)
            {
                if (this.As.Count == 0) break;

                Reactant A = this.As.Dequeue();

                for (int j = 0; j < this.Volume; j++)
                {
                    this.B_s.Enqueue(A.Resolve());
                }

                this.A_s.Enqueue(A);
            }
        }
    }
}
